﻿#include "VideoProgram.h"

VideoProgram::VideoProgram()
{
    
}

VideoProgram::~VideoProgram()
{
    
}

void VideoProgram::draw(std::shared_ptr<VideoBuffer> videoBuffer, void* winId)
{
    if (!videoBuffer || !winId)
    {
        return;
    }

    std::shared_ptr<unsigned char>& bufferData = videoBuffer->buffer;
    int width = videoBuffer->width;
    int height = videoBuffer->height;
    ImageType type = videoBuffer->type;

    unsigned char* yuvData = bufferData.get();
    unsigned char* frame_data[3];

    switch (type)
    {
    case ImageType::YUYV422:
    {
        frame_data[0] = yuvData;
        frame_data[1] = yuvData;
        frame_data[2] = yuvData;
        break;
    }
    case ImageType::YUV422:
    {
        frame_data[0] = yuvData;
        frame_data[1] = yuvData + width * height;
        frame_data[2] = yuvData + width * height * 3 / 2;
        break;
    }
    case ImageType::YUV420:
    {
        frame_data[0] = yuvData;
        frame_data[1] = yuvData + width * height;
        frame_data[2] = yuvData + width * height * 5 / 4;
        break;
    }
    case ImageType::RGB:
    case ImageType::RGBA:
    {
        frame_data[0] = yuvData;
        break;
    }
    default:
        return;
    }

    RenderContext* render = nullptr;

    // 取出窗口对应的上下文
    if (_renders.find(winId) == _renders.end())
    {
        render = new RenderContext((EGLNativeWindowType)winId);
        _renders[winId] = std::shared_ptr<RenderContext>(render);
    }
    else
    {
        render = _renders.at(winId).get();
    }

    // 渲染操作
    render->eglContext()->use();
    render->glesContext()->setup(type);
    render->updateImage((void**)frame_data, width, height);
    render->draw();
}

RenderContext* VideoProgram::contextForWindId(void* winId)
{
    RenderContext* render = nullptr;

    // 取出窗口对应的上下文
    if (_renders.find(winId) == _renders.end())
    {
        render = new RenderContext((EGLNativeWindowType)winId);
        _renders[winId] = std::shared_ptr<RenderContext>(render);
    }
    else
    {
        render = _renders.at(winId).get();
    }

    return render;
}

void VideoProgram::removeWinId(void* winId)
{
    if (_renders.find(winId) == _renders.end())
    {
        return;
    }

    _renders.erase(winId);
}

void VideoProgram::clearWinId()
{
    _renders.clear();
}